package com.datang.litejvm.print;

import com.datang.litejvm.constant.*;

/**
 * @author: 顶风少年
 * @Description: 打印常量池位置打印
 * @date: 16:12 2022/6/14
 **/
public class PrintTextVisitor implements Visitor {
    ConstantPool pool;

    public PrintTextVisitor(ConstantPool pool) {
        this.pool = pool;
    }

    @Override
    public void visit(ConstantMethodRefInfo info) {
        String ref = setBlank("#" + info.getClassIndex() + "." + "#" + info.getNameAndTypeIndex());
        System.out.println(info.getValue() + "        " + ref + "// " + getConstantMethodRefInfoText(info));
    }

    @Override
    public void visit(ConstantFieldRefInfo info) {
        String ref = setBlank("#" + info.getClassIndex() + "." + "#" + info.getNameAndTypeIndex());
        System.out.println(info.getValue() + "         " + ref + "// " + getConstantFieldRefInfoText(info));
    }

    @Override
    public void visit(ConstantStringInfo info) {
        String ref = setBlank("#" + info.getIndex());
        System.out.println(info.getValue() + "           " + ref + "// " + getConstantStringInfoText(info));
    }

    @Override
    public void visit(ConstantClassInfo info) {
        String ref = setBlank("#" + info.getNameIndex());
        System.out.println(info.getValue() + "            " + ref + "// " + getConstantClassInfoText(info));
    }

    @Override
    public void visit(ConstantUTF8Info info) {
        System.out.println(info.getValue() + "             " + "" + info.getBytes());
    }

    @Override
    public void visit(ConstantNameAndTypeInfo info) {
        String ref = setBlank("#" + info.getNameIndex() + "." + "#" + info.getDescriptorIndex());
        System.out.println(info.getValue() + "      " + ref + "// " + getConstantNameAndTypeInfoText(info));
    }

    @Override
    public void visit(ConstantNullConstantInfo info) {
    }

    /**
     * @author: 顶风少年
     * @Description: 常量池引用后边最大的长度
     * @date: 18:15 2022/6/14
     **/
    public int getTableMaxSize() {
        int size = pool.getSize();
        String sSize = size + "";
        return sSize.length() * 2 + 3 + 5;
    }

    public String setBlank(String begin) {
        int blankSize = getTableMaxSize() - begin.length();
        for (int i = 0; i < blankSize; i++) {
            begin = begin + " ";
        }
        return begin;
    }

    public String getConstantUTF8InfoText(ConstantUTF8Info constantUTF8Info) {
        String bytes = constantUTF8Info.getBytes();
        if (bytes.equals("<init>")) {
            bytes = "“" + "<init>" + "”";
        }
        return bytes;
    }

    public String getConstantClassInfoText(ConstantClassInfo constantClassInfo) {
        ConstantUTF8Info constantUTF8Info = (ConstantUTF8Info) pool.getConstantInfo(constantClassInfo.getNameIndex());
        return getConstantUTF8InfoText(constantUTF8Info);
    }

    public String getConstantStringInfoText(ConstantStringInfo constantStringInfo) {
        ConstantUTF8Info constantUTF8Info = (ConstantUTF8Info) pool.getConstantInfo(constantStringInfo.getIndex());
        return getConstantUTF8InfoText(constantUTF8Info);
    }

    public String getConstantNameAndTypeInfoText(ConstantNameAndTypeInfo constantNameAndTypeInfo) {
        ConstantUTF8Info constantUTF8Info = (ConstantUTF8Info) pool.getConstantInfo(constantNameAndTypeInfo.getNameIndex());
        ConstantUTF8Info constantUTF8Info2 = (ConstantUTF8Info) pool.getConstantInfo(constantNameAndTypeInfo.getDescriptorIndex());
        return getConstantUTF8InfoText(constantUTF8Info) + ":" + getConstantUTF8InfoText(constantUTF8Info2);
    }

    public String getConstantFieldRefInfoText(ConstantFieldRefInfo constantFieldRefInfo) {
        ConstantClassInfo constantClassInfo = (ConstantClassInfo) pool.getConstantInfo(constantFieldRefInfo.getClassIndex());
        ConstantNameAndTypeInfo constantNameAndTypeInfo = (ConstantNameAndTypeInfo) pool.getConstantInfo(constantFieldRefInfo.getNameAndTypeIndex());
        return getConstantClassInfoText(constantClassInfo) + "." + getConstantNameAndTypeInfoText(constantNameAndTypeInfo);
    }

    public String getConstantMethodRefInfoText(ConstantMethodRefInfo constantMethodRefInfo) {
        ConstantClassInfo constantClassInfo = (ConstantClassInfo) pool.getConstantInfo(constantMethodRefInfo.getClassIndex());
        ConstantNameAndTypeInfo constantNameAndTypeInfo = (ConstantNameAndTypeInfo) pool.getConstantInfo(constantMethodRefInfo.getNameAndTypeIndex());
        return getConstantClassInfoText(constantClassInfo) + "." + getConstantNameAndTypeInfoText(constantNameAndTypeInfo);
    }
}
